package cn.percent.parse;

import cn.percent.config.RedisConfig;
import com.sun.org.apache.xpath.internal.operations.Bool;
import org.apache.ibatis.reflection.MetaObject;
import org.apache.ibatis.reflection.SystemMetaObject;

import java.io.IOException;
import java.io.InputStream;
import java.util.Map;
import java.util.Properties;

public class RedisConfigurationBuilder {
    private static final RedisConfigurationBuilder INSTANCE = new RedisConfigurationBuilder();
    private static final String SYSTEM_PROPERTY_REDIS_PROPERTIES_FILENAME = "redis.properties.filename";
    private static final String REDIS_RESOURCE = "redis.properties";
    private final String redisPropertiesFilename;

    private RedisConfigurationBuilder(){
        redisPropertiesFilename = System.getProperty(SYSTEM_PROPERTY_REDIS_PROPERTIES_FILENAME, REDIS_RESOURCE);
    }

    public static RedisConfigurationBuilder getInstance() {
        return INSTANCE;
    }

    public RedisConfig parseConfiguration() throws Exception {
        return parseConfiguration(getClass().getClassLoader());
    }

    public RedisConfig parseConfiguration(ClassLoader classLoader) throws Exception {
        Properties properties = new Properties();
        InputStream resourceAsStream = classLoader.getResourceAsStream(redisPropertiesFilename);
        if (properties != null) {
            try {
                properties.load(resourceAsStream);
            } catch (IOException e) {
                throw new RuntimeException(
                        "An error occurred while reading classpath property '"
                             + redisPropertiesFilename
                             + "', sea nested exception",e);

            } finally {
                try {
                    resourceAsStream.close();
                } catch (IOException e) {

                }
            }
        }
        RedisConfig redisConfig = new RedisConfig();
        setConfigProperties(properties,redisConfig);
        return redisConfig;
    }

    private void setConfigProperties(Properties properties, RedisConfig jedisConfig) throws Exception {
        if (properties != null) {
            MetaObject metaObject = SystemMetaObject.forObject(jedisConfig);
            for (Map.Entry<Object,Object> entry : properties.entrySet()) {
                String name = (String) entry.getKey();
                String value = (String) entry.getValue();
                if(metaObject.hasSetter(name)){
                    Class<?> type = metaObject.getSetterType(name);
                    if (String.class == type ) {
                        metaObject.setValue(name,value);
                    } else if (int.class == type || Integer.class == type) {
                        metaObject.setValue(name,Integer.valueOf(value));
                    } else if (long.class == type || Long.class == type) {
                        metaObject.setValue(name,Long.valueOf(value));
                    } else if (short.class == type || Short.class == type) {
                        metaObject.setValue(name,Short.valueOf(value));
                    } else if (byte.class == type || Byte.class == type) {
                        metaObject.setValue(name,Byte.valueOf(value));
                    } else if (float.class == type || Float.class == type) {
                        metaObject.setValue(name,Float.valueOf(value));
                    } else if (boolean.class == type || Boolean.class == type) {
                        metaObject.setValue(name,Boolean.valueOf(value));
                    } else if (double.class == type || Double.class == type) {
                        metaObject.setValue(name,Double.valueOf(value));
                    } else {
                        throw new Exception("Unsupported property type: '" + name + "'of type " + type);
                    }
                }
            }
        }
    }

}
